/**
 * Copyright (C) 2013 DaiKit.com - daikit4gxt module (admin@daikit.com)
 *
 *         Project home : http://code.daikit.com/daikit4gxt
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.daikit.daikit4gxt.client.ui.popup;

import java.util.ArrayList;
import java.util.List;

import com.daikit.commons.shared.bean.AbstractDkBeanWithId;
import com.daikit.daikit4gxt.client.DkBaseMain;
import com.daikit.daikit4gxt.client.action.DkBaseAction;
import com.daikit.daikit4gxt.client.action.DkBaseAsyncCallback;
import com.daikit.daikit4gxt.client.editor.DkPreFlushVisitor;
import com.daikit.daikit4gxt.client.log.DkLogger;
import com.google.gwt.editor.client.Editor;
import com.sencha.gxt.widget.core.client.form.Field;


/**
 * A class to extend for Dialog box for edition or creation of bean
 *
 * @author tcaselli
 * @version $Revision$ Last modifier: $Author$ Last commit: $Date$
 * @param <BEANTYPE>
 *           edited bean type
 * @param <EDITORTYPE>
 *           {@link Editor} type (editor for type B)
 * @param <STORETYPE>
 *           the type of the grid to which the bean should then bean added or updated
 */
public abstract class DkLocalEditCreateProxyPopup<BEANTYPE extends AbstractDkBeanWithId, STORETYPE extends AbstractDkBeanWithId, EDITORTYPE extends Editor<BEANTYPE>>
		extends DkEditCreateProxyPopup<BEANTYPE, STORETYPE, EDITORTYPE>
{

	protected DkLocalEditCreateProxyPopup(final EDITORTYPE editor)
	{
		this(editor, 1);
	}

	protected DkLocalEditCreateProxyPopup(final EDITORTYPE editor, final int numberOfColumns)
	{
		super(editor, numberOfColumns);
	}

	protected DkLogger log = DkLogger.getLog(getClass());

	protected final List<Field<?>> fieldsToValidate = new ArrayList<Field<?>>();

	private boolean showAfterSaveConfirmation = true;

	@Override
	protected void onButtonSaveClicked()
	{
		final DkBaseAction<STORETYPE> actionConvertResult = getConvertResultAction();
		final DkBaseAction<BEANTYPE> actionSave = new DkBaseAction<BEANTYPE>(getLabelActionSaveLoadingLabel())
		{
			@Override
			protected void run()
			{
				//				final List<EditorError> errors = new ArrayList<EditorError>();
				//				getSetupDriver().accept(new PreFlushValidator());
				//				getSetupDriver().accept(new ErrorCollector(errors));
				getSetupDriver().accept(new DkPreFlushVisitor(true));
				final BEANTYPE updatedModel = getSetupDriver().flush();
				if (getSetupDriver().hasErrors() || !applyCustomValidation(updatedModel))
				{
					showErrorPopup();
					stopChain();
				}
				else
				{
					onModelSaved(updatedModel);
				}
				onSuccess(updatedModel);
			}
		};
		if (actionConvertResult != null)
		{
			actionSave.setLastChainAction(actionConvertResult);
		}
		@SuppressWarnings("unchecked")
		final DkBaseAction<Void> actionAfterSave = new DkBaseAction<Void>(DkBaseMain.i18n().action_update_screen_loading_label())
		{
			@Override
			protected void run()
			{
				final STORETYPE previousActionResult = (STORETYPE) getPreviousActionResult();
				if (previousActionResult != null && showAfterSaveConfirmation)
				{
					DkMessageBox.info(getLabelPopupSaveOkMessageBoxTitle(), getLabelPopupSaveOkMessageBoxMessage(), new DkMessageBox.AfterCloseListener()
					{
						@Override
						public void afterClose()
						{
							onAfterSave(previousActionResult);
							onSuccess();
						}
					});
				}
				else
				{
					onAfterSave(previousActionResult);
					onSuccess();
				}
			}
		};
		actionSave.setLastChainAction(actionAfterSave);
		actionSave.execute();
	}

	/**
	 * Permits to update parent model pointer or parent model list of this bean for example
	 *
	 * @param updatedModel
	 *           the model updated
	 */
	protected abstract void onModelSaved(final BEANTYPE updatedModel);

	/**
	 * @return true if valid, false otherwise
	 */
	protected boolean isValid()
	{
		return !getSetupDriver().hasErrors();
	}

	/**
	 * @param updatedModel
	 *           the flushed model
	 * @return whether the custom validation is ok or not
	 */
	protected boolean applyCustomValidation(final BEANTYPE updatedModel)
	{
		return true;
	}


	@Override
	protected void callCreateRpc(final BEANTYPE bean, final DkBaseAsyncCallback<BEANTYPE> callback)
	{
		// Not used.
	}

	@Override
	protected void callUpdateRpc(final BEANTYPE bean, final DkBaseAsyncCallback<BEANTYPE> callback)
	{
		// Not used.
	}

	/**
	 * @return the showAfterSaveConfirmation
	 */
	public boolean isShowAfterSaveConfirmation()
	{
		return showAfterSaveConfirmation;
	}

	/**
	 * @param showAfterSaveConfirmation
	 *           the showAfterSaveConfirmation to set
	 */
	public void setShowAfterSaveConfirmation(final boolean showAfterSaveConfirmation)
	{
		this.showAfterSaveConfirmation = showAfterSaveConfirmation;
	}

}
